package com.supinfo.bonjoursupinfo.fragments;

import java.util.ArrayList;

import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
import android.view.InflateException;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Toast;

import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.OnInfoWindowClickListener;
import com.google.android.gms.maps.LocationSource;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.supinfo.bonjoursupinfo.R;
import com.supinfo.bonjoursupinfo.controller.loader.MyMapLoaderFromBdd;
import com.supinfo.bonjoursupinfo.controller.loader.MyMapLoaderRefresh;
import com.supinfo.bonjoursupinfo.models.Place;

public class MyMapFragment extends Fragment  implements OnInfoWindowClickListener, 
														LocationListener, LocationSource,
														GoogleMap.OnMarkerClickListener,
														LoaderManager.LoaderCallbacks<ArrayList<Place>>{

	private static final int LOADER_LIST_FROM_BDD = 0x01;
	private static final int LOADER_LIST_REFRESH = 0x02;
	
	private ArrayList<Place> positionsArray;
	private View mView;
	private LocationManager lm;
	private double latitude;
	private double longitude;
	private double altitude;
	private float accuracy;
	private boolean loading = true;
	private String provider;
	private GoogleMap mMap;
	private Location myLoca;
	
	private MenuItem menuRefresh;
	private MenuItem menuLoad;
	
	@Override
	public void onCreate(Bundle savedInstanceState){
		super.onCreate(savedInstanceState);
		
		this.setHasOptionsMenu(true);
	}
	
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
		
		if (mView != null) {
	        ViewGroup parent = (ViewGroup) mView.getParent();
	        if (parent != null)
	            parent.removeView(mView);
	    }
	    try {
	    	mView = inflater.inflate(R.layout.fragment_map, container, false);
	    } catch (InflateException e) {
	    }
		setUpMapIfNeeded();
		mMap.setOnInfoWindowClickListener(this);
		setUpMap();
		mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(43.6674891,7.2130581), 14.0f));
		
		this.getLoaderManager().initLoader(LOADER_LIST_FROM_BDD, null, this);
		return mView;
	}
	
	@Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
		super.onCreateOptionsMenu(menu, inflater);
        inflater.inflate(R.menu.fragment_mymap, menu);
        
        menuRefresh = menu.findItem(R.id.action_refresh);
        menuLoad = menu.findItem(R.id.item_progress_loading);
        
        if(loading){
        	menuRefresh.setVisible(false);
        } else {
        	menuLoad.setVisible(false);
        }
    }
	
	public boolean onOptionsItemSelected(MenuItem item) {
	    switch (item.getItemId()) {
	    case R.id.action_refresh:
	    	this.getLoaderManager().restartLoader(LOADER_LIST_REFRESH, null, this);
	    	return true;
	    }
	    return super.onOptionsItemSelected(item);
	}

	public static MyMapFragment createFragment(){
		return new MyMapFragment();
	}

	private void setUpMap() 
	{
		mMap.setMyLocationEnabled(true);
		
		getActivity().getApplicationContext();
		lm = (LocationManager) getActivity().getSystemService(Context.LOCATION_SERVICE);
		if (lm.isProviderEnabled(LocationManager.GPS_PROVIDER))
			lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10000, 0, this);
		lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 10000, 0, this);
	}
	
	private void setUpMapIfNeeded() {
	    // Do a null check to confirm that we have not already instantiated the map.
	    if (mMap == null) 
	    {
	        // Try to obtain the map from the SupportMapFragment.
	        mMap = ((SupportMapFragment) getActivity().getSupportFragmentManager().findFragmentById(R.id.access_grandstand_map)).getMap();
	        
	        if(isGoogleMapsInstalled())
	        {
	            if (mMap != null) 
	            {
	            }
	        }
	        else
	        {
	            Builder builder = new AlertDialog.Builder(getActivity());
	            builder.setMessage("Please install Google Maps");
	            builder.setCancelable(false);
	            builder.setPositiveButton("ok", null);
	            AlertDialog dialog = builder.create();
	            dialog.show();
	        }
	    }
	}
	
	private void refreshLocation(){
		Criteria criteria = new Criteria();
		provider = lm.getBestProvider(criteria, true);
		myLoca = lm.getLastKnownLocation(provider);
	}
	
	private void putInterestPointsOnMap()
	{
		refreshLocation();
		
		mMap.setOnMarkerClickListener(this);
		mMap.setOnInfoWindowClickListener(this);
		
		if(positionsArray == null){
			positionsArray = new ArrayList<Place>();
		}
		
		if (myLoca != null)
		{
			if (positionsArray != null)
			{
				if (!positionsArray.isEmpty())
				{
					for (Place pos : positionsArray)
					{
						float lat;
						float lon;
						
						lat = pos.getLatitude();
						lon = pos.getLongitude();
						
						MarkerOptions markerOptions = new MarkerOptions().position(new LatLng(lat, lon));

						Marker marker = mMap.addMarker(markerOptions);
						
						if (pos.getName() != null || pos.getName() != "")
						{
							marker.setTitle(pos.getName());
						}
						if (pos.getDescription() != null || pos.getDescription() != "")
						{
							marker.setSnippet(pos.getDescription());
						}
					}
				}
			}
		}
		else
		{
			Toast.makeText(getActivity(), "Cannot retrieve positions, ensure your location " +
					"system is ON.\n", Toast.LENGTH_LONG).show();
		}
	}
	
	public void clearMarkers(){
		mMap.clear();
	}
	
	public boolean isGoogleMapsInstalled()
	{
	    try
	    {
	        ApplicationInfo info = getActivity().getPackageManager().
	        		getApplicationInfo("com.google.android.apps.maps", 0 );
	        return true;
	    } 
	    catch(PackageManager.NameNotFoundException e)
	    {
	        return false;
	    }
	}

	public OnClickListener getGoogleMapsListener()
	{
	    return new OnClickListener() 
	    {
	        public void onClick(DialogInterface dialog, int which) 
	        {
	            Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=com.google.android.apps.maps"));
	            startActivity(intent);

	            //Finish the activity so they can't circumvent the check
	            getActivity().finish();
	        }

			public void onClick(View v) {
				// TODO Auto-generated method stub
				
			}
	    };
	}
	
	
	public void activate(OnLocationChangedListener arg0) {
		// TODO Auto-generated method stub
		
	}

	public void deactivate() {
		// TODO Auto-generated method stub
		
	}

	public void onLocationChanged(Location location) {
		latitude = location.getLatitude();
		longitude = location.getLongitude();
		altitude = location.getAltitude();
		accuracy = location.getAccuracy();

	}

	public void onProviderDisabled(String provider) {
	}

	public void onProviderEnabled(String provider) {
	}

	public void onStatusChanged(String provider, int status, Bundle extras) {
		String newStatus = "";
		switch (status) {
			case LocationProvider.OUT_OF_SERVICE:
				newStatus = "OUT_OF_SERVICE";
				break;
			case LocationProvider.TEMPORARILY_UNAVAILABLE:
				newStatus = "TEMPORARILY_UNAVAILABLE";
				break;
			case LocationProvider.AVAILABLE:
				newStatus = "AVAILABLE";
				break;
		}
	}

	@Override
	public Loader<ArrayList<Place>> onCreateLoader(int id, Bundle args) {
		this.setLoading(true);
		
		switch(id){
		case LOADER_LIST_FROM_BDD:
			return new MyMapLoaderFromBdd(this.getActivity());
		case LOADER_LIST_REFRESH:
			return new MyMapLoaderRefresh(this.getActivity());
		}
		return null;
	}

	@Override
	public void onLoadFinished(Loader<ArrayList<Place>> loader, ArrayList<Place> list) {
		switch(loader.getId()){
		case LOADER_LIST_FROM_BDD:
			if(list.size() == 0){
				MyMapFragment.this.getLoaderManager().initLoader(LOADER_LIST_REFRESH, null, MyMapFragment.this);
				return;
			}
		case LOADER_LIST_REFRESH:
			positionsArray = list;
			
			refreshLocation();
			if(myLoca == null){
				lm.requestLocationUpdates(provider, 0, 0, new LocationListener(){

					@Override
					public void onLocationChanged(Location location) {
						myLoca = location;
					}

					@Override
					public void onProviderDisabled(String provider) {
						
					}

					@Override
					public void onProviderEnabled(String provider) {
						
					}

					@Override
					public void onStatusChanged(String provider, int status,
							Bundle extras) {
						
					}
					
				});
			} else {
				clearMarkers();
				putInterestPointsOnMap();
				this.setLoading(false);
			}
			
			break;
		}
		
		return;
	}

	@Override
	public void onLoaderReset(Loader<ArrayList<Place>> cursor) {
		
	}
	
	private void setLoading(boolean loading){
		this.loading = loading;
		if(menuLoad == null || menuRefresh == null){
			return;
		}
		
		if(loading){
			menuLoad.setVisible(true);
			menuRefresh.setVisible(false);
		} else {
			menuLoad.setVisible(false);
			menuRefresh.setVisible(true);
		}
	}

	@Override
	public boolean onMarkerClick(Marker marker) {
		return false;
	}

	@Override
	public void onInfoWindowClick(Marker marker) {
		LatLng position = marker.getPosition();
		try{
			Intent intent = new Intent(Intent.ACTION_VIEW, 
			Uri.parse("http://maps.google.com/maps?f=d&daddr="+position.latitude+","+position.longitude));
			intent.setComponent(new ComponentName("com.google.android.apps.maps", "com.google.android.maps.MapsActivity"));
			startActivity(intent);
	}catch (Exception e){
		e.printStackTrace();
		Toast.makeText(mView.getContext(), "Google map is required", Toast.LENGTH_SHORT).show();
	}
		
	}
}
